﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using HisGL.Core;
using HisGL.CA.NetCA;

namespace HisGL.CA
{
  public class CAManager
  {
      private static CAManager instance = new CAManager();
      private string Host = "";
      public bool UseTimestamp { get; set; }
      public bool NeedVerifySign { get; set; }

      private CAManager()
      {
            //RefreshCACfg();
            Host = "https://wx.51ht.com";

      }

      public static CAManager Instance
      {
          get
          {
              return instance;
          }
      }

      public ResCA<CALoginInfo> CALogin(UserInfo UserInfo, ReqCALogin req)
      {
        ResCA<CALoginInfo> res = new ResCA<CALoginInfo>();
        res.Data = new CA.CALoginInfo();
        res.Code = -1;
        if (req.UserUid == "")
        {
          res.Message = "传入用户工号为空！";
          return res;
        }

        ResCA<string> resCert = GetUserCert(req.UserUid);
        if (resCert.Code < 0)
        {
          res.Code = resCert.Code;
          res.Message = resCert.Message;
          return res;
        }

        string sUserCert = resCert.Data;
        //先查询证书
        using (NetCAApi CaApi = new NetCAApi(Host))
        {
          //登录
          //使用当前输入的用户名登录
          ReqNetCA.Cert Cert = new ReqNetCA.Cert(){ CertContent = sUserCert };
          ResNetCA.LoginResponse resLogin = CaApi.UserCertContentDoLogin(req.UserPin, Cert, req.ApplicationId);
          if (!resLogin.ResponseResult.Success)
          {
            res.Message = resLogin.ResponseResult.Message;
            //2.1.6证书用户口令重试次数
            ResNetCA.QueryPasswordRetryCountResponse resNum = CaApi.CertContentGetSurplusNum(Cert);
            if (!resNum.ResponseResult.Success)
            {
              res.Message = res.Message + "\r\n" + resNum.ResponseResult.Message;
            }
            else
            {
              res.Message = res.Message + "\r\n" + string.Format("还剩下{0}次后锁定！", resNum.Contents); 
            }
                        
            return res;
          }
          res.Data.UserToken = resLogin.Contents.UserToken;
          res.Data.UserUid = req.UserUid;
          res.Code = 0;
          
        }

        return res;
      }

      public ResCA<CASign> CASign(UserInfo UserInfo, ReqCASign req)
      {
        ResCA<CASign> res = new ResCA<CASign>();
        res.Data = new CA.CASign();
        res.Code = -1;
        using (NetCAApi CaApi = new NetCAApi(Host))
        {
          ResNetCA.OprInfoResponse resUid = CaApi.OprinfoSearch(req.UserToken);
          if (!resUid.ResponseResult.Success)
          {
            res.Message = "CaApi.OprinfoSearch:" + resUid.ResponseResult.Message;
            return res;
          }
          if (resUid.IsValid)
          {
            res.Data.UserType = resUid.Contents.UserType;
            res.Data.UserUid = resUid.Contents.Uid;
            res.Data.AuthorizedUserId = resUid.Contents.AuthorizedUserId != null ? resUid.Contents.AuthorizedUserId : "" ;
          }          
        
          string sOriginData = Convert.ToBase64String(Encoding.UTF8.GetBytes(req.OriginData));
          bool detached = false;
          bool useSubjectKeyId = false;
          int includeCertOption = 0;
          bool useQ7 = false;
          ResNetCA.SignResponse resSign = CaApi.PkiSignData(sOriginData, detached, useSubjectKeyId, includeCertOption, useQ7, req.UseTimestamp, req.UserToken);
          if (!resSign.ResponseResult.Success)
          {
            res.Message = resSign.ResponseResult.Message;
            return res;
          }
          res.Data.OriginDataBase64 = sOriginData;
          res.Data.SignedData = resSign.Contents.SignedData;
                

          //下载签名图片
          if (req.DownLoadSealPic)
          {
            ResNetCA.DownloadSealResponse resSealPic = CaApi.SealDownloadSealPic(req.UserToken);
            if (!resSealPic.ResponseResult.Success)
            {
              res.Message = "CaApi.SealDownloadSealPic:" + resSealPic.ResponseResult.Message;
              return res;
            }

            res.Data.SealPicBase64 = resSealPic.Contents.SealImageBase64;
          }

          //验证签名
          if (req.NeedVerifySign)
          {
            bool includeCert = false;  //false 时不需要 ReqNetCA.Cert Cert ？
            ReqNetCA.Cert Cert = new ReqNetCA.Cert(); //签名证书 { CertContent = resUid.Contents.SignCert }
            ResNetCA.BasicResponse resVerify = CaApi.PkiVerifySignData(sOriginData, detached, res.Data.SignedData, req.UseTimestamp, includeCert, Cert);
            if (!resVerify.ResponseResult.Success)
            {
              res.Message = "CaApi.PkiVerifySignData:" + resVerify.ResponseResult.Message;
              return res;
            }
          }

          res.Code = 0;
        }


        return res;
      }

      public ResCA<CAQRCode> CAQRCode(UserInfo UserInfo, ReqCAQRCode req)
      {
        ResCA<CAQRCode> res = new ResCA<CAQRCode>();
        res.Data = new CA.CAQRCode();
        res.Code = -1;
        using (NetCAApi CaApi = new NetCAApi(Host))
        {
          if (req.UserUid != "")
          {
            ResCA<string> resCert = GetUserCert(req.UserUid);
            if (resCert.Code < 0)
            {
              res.Code = resCert.Code;
              res.Message = resCert.Message;
              return res;
            }
            ReqNetCA.Cert Cert = new ReqNetCA.Cert() { CertContent = resCert.Data };
            ResNetCA.GenerateQrCodeResponse resQR = CaApi.LoginQRCode(req.LoginTypeBitValue, Cert);
            if (!resQR.ResponseResult.Success)
            {
              res.Message = resQR.ResponseResult.Message;
              return res;
            }

            res.Data.QRCodeBase64 = resQR.Contents.QrCodeBase64;
            res.Data.QRCodeIdentity = resQR.Contents.QrCodeIdentity;
            res.Data.QRExpireDate = resQR.Contents.QrCodeExpireDate;

            res.Code = 0;
          }
          else
          {
            ReqNetCA.Cert Cert = new ReqNetCA.Cert();
            ResNetCA.GenerateNoStatusQrCodeResponse resNS = CaApi.LoginQRCodeNoStatus2CKV1(req.LoginTypeBitValue, Cert);
            if (!resNS.ResponseResult.Success)
            {
              res.Message = resNS.ResponseResult.Message;
              return res;
            }

            if (resNS.Contents.QrCodes.Count == 0)
            {
              res.Message = "服务端响应返回的qrCodes字段为空";
              return res;
            }

            res.Data.QRCodeBase64 = resNS.Contents.QrCodes[0].QrCodeBase64;
            res.Data.QRCodeIdentity = resNS.Contents.QrCodeIdentity;
            res.Data.QRExpireDate = resNS.Contents.QrCodeExpireDate;

            res.Code = 0;

          }

        }

        return res;
      }

      public ResCA<CALoginInfo> CAQRLogin(UserInfo UserInfo, ReqCAQRLogin req)
      {
        ResCA<CALoginInfo> res = new ResCA<CALoginInfo>();
        res.Data = new CA.CALoginInfo();
        res.Code = -1;

        //先查询证书
        using (NetCAApi CaApi = new NetCAApi(Host))
        {
          //登录
          //使用当前输入的用户名登录
          ResNetCA.QueryQrCodeStatusResponse resLogin = CaApi.QRCodeStatus(req.QRCodeIdentity);
          if (!resLogin.ResponseResult.Success)
          {
            res.Message = resLogin.ResponseResult.Message;
            return res;
          }

          if (resLogin.Contents.VerifyStatus == 0)
          {
            res.Data.UserToken = resLogin.Contents.UserToken;

            ResNetCA.OprInfoResponse resUid = CaApi.OprinfoSearch(res.Data.UserToken);
            if (!resUid.ResponseResult.Success )
            {
              res.Message = resUid.ResponseResult.Message;
              return res;
            }

            if (resUid.IsValid)
            {
              res.Data.UserUid = resUid.Contents.Uid;
            }

            res.Code = 0;
          }
          else
          {
            res.Message = resLogin.Contents.ErrorMessage;

          }
          
          
        }

        return res;
      }

      public ResCA<CASignPdf> CASignPdf(UserInfo UserInfo, ReqCASignPdf req)
      {
        ResCA<CASignPdf> res = new ResCA<CASignPdf>();
        res.Data = new CA.CASignPdf();
        res.Code = -1;
        using (NetCAApi CaApi = new NetCAApi(Host))
        {
          ResNetCA.OprInfoResponse resUid = CaApi.OprinfoSearch(req.UserToken);
          if (!resUid.ResponseResult.Success)
          {
            res.Message = "CaApi.OprinfoSearch:" + resUid.ResponseResult.Message;
            return res;
          }
          if (resUid.IsValid)
          {
            res.Data.UserType = resUid.Contents.UserType;
            res.Data.UserUid = resUid.Contents.Uid;
            res.Data.AuthorizedUserId = resUid.Contents.AuthorizedUserId != null ? resUid.Contents.AuthorizedUserId : "";
          }

          var originPdfBytes = File.ReadAllBytes(req.FilePath);

          string sPdfData = Convert.ToBase64String(originPdfBytes);
          ReqNetCA.SealSize sealSize = new ReqNetCA.SealSize {Width = req.Width,Height = req.Height };
          ReqNetCA.Position position = new ReqNetCA.Position {X = req.X,Y = req.Y,Page = req.Page };
          string fieldName = req.FieldName;
          string fieldText = req.FieldText;
          bool useFieldText = req.UseFieldText;

          ResNetCA.PDFSignSealResponse resSign = CaApi.SealPdf(sPdfData, sealSize, position, fieldName, fieldText, useFieldText, req.UseTimestamp, req.UserToken);
          if (!resSign.ResponseResult.Success)
          {
            res.Message = resSign.ResponseResult.Message;
            return res;
          }
          res.Data.PDFBase64 = sPdfData;
          res.Data.SignedPDFBase64 = resSign.Contents.SignedPDFBase64;


          //下载签名图片
          if (req.DownLoadSealPic)
          {
            ResNetCA.DownloadSealResponse resSealPic = CaApi.SealDownloadSealPic(req.UserToken);
            if (!resSealPic.ResponseResult.Success)
            {
              res.Message = "CaApi.SealDownloadSealPic:" + resSealPic.ResponseResult.Message;
              return res;
            }

            res.Data.SealPicBase64 = resSealPic.Contents.SealImageBase64;
          }

          res.Code = 0;
        }


        return res;
      }

      private ResCA<string> GetUserCert(string sUserUid)
      {
        ResCA<string> res = new ResCA<string>();
        res.Code = -1;        
        
        //先查询证书
        using (NetCAApi CaApi = new NetCAApi(Host))
        {
          ResNetCA.QueryCertResponse resCert = CaApi.CertSearch(sUserUid);

          if (!resCert.ResponseResult.Success)
          {
            res.Message = string.Format("查询证书失败：{0}", resCert.ResponseResult.Message);
            return res;
          }
          if (!resCert.IsValid)
          {
            res.Message = string.Format("找不到{0}的相关证书", sUserUid);
            return res;
          }

          //把查询到的证书缓存起来
          string id = sUserUid;
          // 由于大小写敏感，所以要先查找对应的真实用户ID
          foreach (string key in resCert.Contents.Keys)
          {
            if (key.Equals(id, StringComparison.CurrentCultureIgnoreCase))
            {
              id = key;
              break;
            }
          }
          var list = resCert.Contents[id];
          res.Data = list.Count > 0 ? list[0] : string.Empty;

          res.Code = 0;

        }
        return res;
      }

  }
}
